package yxy.game.pm2.module.matchonline;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.joda.time.DateTime;
import org.redisson.api.RList;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.game.pm2.bean.db.newDao.MatchOnlineRecordDAO;
import yxy.game.pm2.bean.db.po.MatchOnlineRecordPo;
import yxy.game.pm2.bean.module.PlayerModule;

import java.util.ArrayList;
import java.util.List;

public class MatchOnlineRecord extends PlayerModule {
    // bean===========================================================================
    private String code;//
    private DateTime date;// 时间
    private ArrayList<String> recordCodes = new ArrayList<>();// 录像码
    private RecordPlayerInfo infoA;// 进攻方
    private RecordPlayerInfo infoB;// 防守方
    private boolean isWin;// 攻方是否胜利

    private BattleResult battleResult;

    public boolean isWin() {
        return isWin;
    }

    public void setWin(boolean win) {
        isWin = win;
    }

    public DateTime getDate() {
        return date;
    }

    public void setDate(DateTime date) {
        this.date = date;
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public ArrayList<String> getRecordCodes() {
        return recordCodes;
    }

    public void setRecordCodes(ArrayList<String> recordCodes) {
        this.recordCodes = recordCodes;
    }

    public RecordPlayerInfo getInfoA() {
        return infoA;
    }

    public void setInfoA(RecordPlayerInfo infoA) {
        this.infoA = infoA;
    }

    public RecordPlayerInfo getInfoB() {
        return infoB;
    }

    public void setInfoB(RecordPlayerInfo infoB) {
        this.infoB = infoB;
    }

    public BattleResult getBattleResult() {
        return battleResult;
    }

    public void setBattleResult(BattleResult battleResult) {
        this.battleResult = battleResult;
    }

    // func===========================================================================
    // redis==========================================================================

    static public String key(String playerCode) {
        return String.format("PLAYER:%s:MODULE:MATCHONLINERECORD", playerCode);
    }

    static private RList<MatchOnlineRecord> touch(String playerCode) throws RedisException {
        return RedisManager.client(redis()).getList(key(playerCode));
    }

    static public List<MatchOnlineRecord> get(String playerCode) {
        try {
            List<MatchOnlineRecord> list = touch(playerCode).readAll();
            if (list.size() == 0) {
                List<MatchOnlineRecordPo> matchOnlineRecordPos = MatchOnlineRecordDAO.getList(playerCode);
                if (matchOnlineRecordPos != null && matchOnlineRecordPos.size() > 0) {
                    for (int i = 0; i < matchOnlineRecordPos.size(); i++) {
                        MatchOnlineRecord matchOnlineRecord = new MatchOnlineRecord();
                        MatchOnlineRecordPo po = matchOnlineRecordPos.get(i);
                        matchOnlineRecord.setPlayerCode(playerCode);
                        matchOnlineRecord.setCode(po.getCode());
                        RecordPlayerInfo infoA = JSON.parseObject(po.getInfoA(), new TypeReference<RecordPlayerInfo>() {
                        });
                        matchOnlineRecord.setInfoA(infoA);
                        RecordPlayerInfo infoB = JSON.parseObject(po.getInfoB(), new TypeReference<RecordPlayerInfo>() {
                        });
                        matchOnlineRecord.setInfoB(infoB);
                        ArrayList<String> recordCodes = JSON.parseObject(po.getRecordCodes(), new TypeReference<ArrayList<String>>() {
                        });
                        matchOnlineRecord.setRecordCodes(recordCodes);
                        matchOnlineRecord.setWin(po.isWin());
                        matchOnlineRecord.setBattleResult(BattleResult.battleResult(po.getBattleResult()));
                        matchOnlineRecord.setDate(new DateTime((po.getDate())));
                        list.add(matchOnlineRecord);
                    }
                    //放回缓存
                    touch(playerCode).addAll(list);
                }
            }

            return list;
        } catch (RedisException e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    static public void add(String playerCode, MatchOnlineRecord record) {
        try {
            RList<MatchOnlineRecord> rlist = touch(playerCode);
            rlist.add(0, record);
            if (rlist.size() > 20) {
                rlist.trim(0, 19);
            }
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    //数据归档到数据库
    public static void saveToDB(String playerCode) {
        try {
            RList<MatchOnlineRecord> rList = touch(playerCode);
            if (rList.isExists()) {
                long updateTime = System.currentTimeMillis();
                //存储
                List<MatchOnlineRecordPo> poList = new ArrayList<>();
                List<MatchOnlineRecord> list = rList.readAll();
                for (int i = 0; i < list.size(); i++) {
                    MatchOnlineRecordPo po = new MatchOnlineRecordPo();
                    po.setPlayerCode(playerCode);
                    po.setCode(list.get(i).getCode());
                    JSONObject infoA = (JSONObject)JSONObject.toJSON(list.get(i).getInfoA());
                    JSONObject infoB = (JSONObject)JSONObject.toJSON(list.get(i).getInfoB());
                    JSONArray jsonArray = (JSONArray)JSONArray.toJSON(list.get(i).getRecordCodes());
                    po.setRecordCodes(jsonArray.toString());
                    po.setInfoA(infoA.toString());
                    po.setInfoB(infoB.toString());
                    po.setWin(list.get(i).isWin());
                    po.setBattleResult(list.get(i).getBattleResult().toString());
                    po.setDate(list.get(i).getDate().toDate());
                    po.setUpdateTime(updateTime);
                    poList.add(po);
                    MatchOnlineRecordDAO.replace(poList);
                }

                // 当且仅当执行过update或者insert操作之后，侧面证明redis数据没问题。此时才能进行delete操作
                MatchOnlineRecordDAO.delete(playerCode, updateTime);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //从redis移走数据
    public static void removeAllFromRedis(String playerCode) {
        try {
            touchBucket(key(playerCode)).delete();
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }
    // lock==========================================================================

    /** 录像用玩家信息快照 */
    static public class RecordPlayerInfo {
        private String playerName;
        private String playerCode;
        private int head;
        private int headFrame;

        public String getPlayerCode() {
            return playerCode;
        }

        public void setPlayerCode(String playerCode) {
            this.playerCode = playerCode;
        }

        public String getPlayerName() {
            return playerName;
        }

        public void setPlayerName(String playerName) {
            this.playerName = playerName;
        }

        public int getHead() {
            return head;
        }

        public void setHead(int head) {
            this.head = head;
        }

        public int getHeadFrame() {
            return headFrame;
        }

        public void setHeadFrame(int headFrame) {
            this.headFrame = headFrame;
        }
    }


    @Override
    public String lockKey() {
        return String.format("lock:%s", key(getPlayerCode()));
    }
}
